package com.tuo51.childcare.service.impl;

import com.tuo51.childcare.domain.ptest.PTestCertificate;
import com.tuo51.childcare.domain.ptest.PTestItem;
import com.tuo51.childcare.domain.ptest.PTestItemRecord;
import com.tuo51.childcare.domain.ptest.PTestStaffExt;
import com.tuo51.childcare.domain.vo.PTestItemAnswerSheetItemVO;
import com.tuo51.childcare.domain.vo.PTestItemOptionVO;
import com.tuo51.childcare.domain.vo.PTestItemVO;
import com.tuo51.childcare.repository.PTestCertificateRepository;
import com.tuo51.childcare.repository.PTestItemRecordRepository;
import com.tuo51.childcare.repository.PTestItemRepository;
import com.tuo51.childcare.repository.PTestStaffExtRepository;
import com.tuo51.childcare.service.PTestService;
import com.tuo51.evaluate.domain.childrens.Children;
import com.tuo51.core.domain.staffs.Staff;
import com.tuo51.foudation.exception.BusinessException;
import com.tuo51.foudation.model.ErrorCode;
import com.tuo51.foudation.query.base.PagerQuery;
import com.tuo51.foudation.utils.CopyUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;
import java.util.Map;

@Service
public class PTestServiceImpl implements PTestService {

    @Autowired
    PTestItemRepository itemRepository;

    @Autowired
    PTestItemRecordRepository recordRepository;

    @Autowired
    PTestCertificateRepository certificateRepository;

    @Autowired
    PTestStaffExtRepository extRepository;

    @Override
    public PTestItem getTestItem(String itemId) {
        return itemRepository.getOne(itemId);
    }

    @Override
    public PTestItem editItem(PTestItemVO pTestItemVO) {

        if (StringUtils.isAnyEmpty(pTestItemVO.getTitle())){
            throw new BusinessException(ErrorCode.PARAM_NOT_BLANK, "参数错误");
        }

        PTestItem s = null;
        if (StringUtils.isNotEmpty(pTestItemVO.getId())){
            s = itemRepository.getOne(pTestItemVO.getId());
        }else{
            s = new PTestItem();
        }

        if (s == null){
            throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "对象不存在");
        }

        CopyUtils.copyProperties(pTestItemVO, s);

        itemRepository.save(s);

        return s;
    }

    @Override
    public boolean deleteItem(String itemId) {

        if (StringUtils.isAnyEmpty(itemId)){
            throw new BusinessException(ErrorCode.PARAM_NOT_BLANK, "参数错误");
        }

        PTestItem s = itemRepository.getOne(itemId);

        if (s == null){
            throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "对象不存在");
        }

        itemRepository.delete(s);

        return false;
    }

    @Override
    public Page<PTestItem> getTestItem(String categoryId, Integer type, Integer month, Integer forDay, String searchBy, PagerQuery pagerQuery) {

//        if (month == null && forDay == null) {
//            throw new BusinessException(ErrorCode.PARAM_NOT_BLANK, "参数错误");
//        }

        return itemRepository.findAll(new Specification<PTestItem>() {
            @Override
            public Predicate toPredicate(Root<PTestItem> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate base = cb.isFalse(root.get("deleted"));

                if(type != null){
                    base = cb.and(base, cb.equal(root.get("itemType"), type));
                }

                if (StringUtils.isNotEmpty(categoryId)) {
                    Predicate p = cb.equal(root.get("categoryId"), categoryId);
                    base = cb.and(base, p);
                }

                if (forDay != null) {
                    Predicate p = cb.equal(root.get("forDay"), forDay);
                    base = cb.and(base, p);
                }else if(month != null){
                    Predicate p1 = cb.lessThanOrEqualTo(root.get("monthMin"), month);
                    Predicate p2 = cb.greaterThan(root.get("monthMax"), month);
                    Predicate p = cb.and(p1, p2);
                    base = cb.and(base, p);
                }

                if (StringUtils.isNotEmpty(searchBy)){
                    String key = "%" + searchBy + "%";
                    Predicate p = cb.or(cb.like(root.get("title"), key),
                            cb.like(root.get("hint"), key));
                    base = cb.and(base, p);
                }


                query.where(base);

                query.orderBy(cb.asc(root.get("dailyIndex")));

                return query.getRestriction();
            }
        }, PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize()));
    }

    @Override
    public List<PTestItem> getDailyTips(String categoryId, Integer month, Integer forDay) {
        return getTestItem(categoryId, PTestItem.ITEMTYPE_TIPS, month, forDay, null, PagerQuery.of(0, 100000)).toList();
    }

    @Override
    public List<PTestItem> getDailyTest(String categoryId, Integer month, Integer forDay) {
        return getTestItem(categoryId, PTestItem.ITEMTYPE_QUESTION, month, forDay,null, PagerQuery.of(0, 100000)).toList();
    }

    @Override
    public Map reportDailyTest(String categoryId, Integer month, Integer daily) {
        return null;
    }

    @Override
    public PTestCertificate parseTestAnswer(Staff staff,
                                            Children children,
                                            String relation,
                                            List<PTestItemAnswerSheetItemVO> answerSheet) {

        //证书
        PTestCertificate certificate = new PTestCertificate();

        certificate.setUid(staff.getId());
        if (children != null) {
            certificate.setChildId(children.getId());
            certificate.setChildName(children.getName());
            certificate.setRelation(children.getExtendInfo().getGuardianRelation());
        }
        certificateRepository.save(certificate);

        int totalGoat = 0;
        int totalCount = 0;

        //开始分析得分
        for (PTestItemAnswerSheetItemVO item : answerSheet){
            //创建测评答题卡
            PTestItemRecord record = new PTestItemRecord();

            //childrenName是否为空
            record.setUid(staff.getId());
            record.setChildrenId(certificate.getChildId());
            record.setOptions(item.getSelections());
            record.setCertificateId(certificate.getId());

            int goat = 0;
            for (PTestItemOptionVO optionVO : item.getSelections()){
                if(optionVO.isAnswer()){
                    goat += 1;
                }
            }
            record.setGoat(goat);

            totalGoat += goat;
            totalCount += 1;

            recordRepository.save(record);
        }

        // 更新用户得分
        PTestStaffExt ext = extRepository.findByUid(staff.getId());
        if (null == ext){
            ext = new PTestStaffExt();
            ext.setUid(staff.getId());
            extRepository.save(ext);
        }

        //保存用户总分
        ext.setCount(totalCount + ext.getCount());
        ext.setGoat(totalGoat + ext.getGoat());
        extRepository.save(ext);

        //生成用户证书
        long total = extRepository.count();
        long less = extRepository.countAllByGoatLessThanEqual(ext.getGoat());

        String percent = total <= less ? "99.9%" :String.format("%.1f%%", less*1.0 / total);

        certificate.setTitle("您答对了" + totalGoat + "道题");
        certificate.setSubTitle("恭喜您超过了" + percent+ "的妈妈");



        certificateRepository.save(certificate);

        return certificate;
    }

    @Override
    public PTestCertificate getPTestCertificate(String certificateId) {
        return certificateRepository.getOne(certificateId);
    }
}
